package v1

import org.joml.Vector2f
import org.lwjgl.glfw.GLFW.*
import org.lwjgl.system.MemoryStack

class KeyBoardMgr {
    private var keyFirstDownCallback: ((Int) -> Unit)? = null
    private var keyUpCallback: ((Int) -> Unit)? = null
    private var keyDownCallback: ((Int) -> Unit)? = null

    fun keyFirstDown(callback: (Int) -> Unit) {
        keyFirstDownCallback = callback
    }

    fun keyDown(callback: (Int) -> Unit) {
        keyDownCallback = callback
    }

    fun keyUp(callback: (Int) -> Unit) {
        keyUpCallback = callback
    }

    fun receiveKeyEvent(key: Int, action: Int) {
        when (action) {
            GLFW_PRESS -> {
                keyFirstDownCallback?.invoke(key)
                keyDownCallback?.invoke(key)
            }
            GLFW_REPEAT -> {
                keyDownCallback?.invoke(key)
            }
            GLFW_RELEASE -> {
                keyUpCallback?.invoke(key)
            }
        }
    }
}

class MouseMgr(val window: Window) {

    var mouseLeftState = false
    var mouseMiddleState = false
    var mouseRightState = false


    var mouseBeginCallback: ((Int, Float, Float) -> Unit)? = null
    var mouseMoveCallback: ((Int, Float, Float) -> Unit)? = null
    var mouseEndCallback: ((Int, Float, Float) -> Unit)? = null

    fun receiverMouseBtnEvent(button: Int, action: Int) {
        when (action) {
            GLFW_PRESS -> {
                when (button) {
                    GLFW_MOUSE_BUTTON_LEFT -> mouseLeftState = true
                    GLFW_MOUSE_BUTTON_RIGHT -> mouseRightState = true
                    GLFW_MOUSE_BUTTON_MIDDLE -> mouseMiddleState = true
                }
                val pos = getCursorPos()
                mouseBeginCallback?.invoke(button,pos.x,pos.y)
            }
            GLFW_RELEASE -> {
                when (button) {
                    GLFW_MOUSE_BUTTON_LEFT -> mouseLeftState = false
                    GLFW_MOUSE_BUTTON_RIGHT -> mouseRightState = false
                    GLFW_MOUSE_BUTTON_MIDDLE -> mouseMiddleState = false
                }
                val pos = getCursorPos()
                mouseEndCallback?.invoke(button,pos.x,pos.y)
            }
        }
    }

//    fun mouseState(button: Int): Boolean {
//        return when (button) {
//            GLFW_MOUSE_BUTTON_LEFT -> mouseLeftState
//            GLFW_MOUSE_BUTTON_RIGHT -> mouseRightState
//            GLFW_MOUSE_BUTTON_MIDDLE -> mouseMiddleState
//            else -> {
//                MyLog.warn("Unknow button:$button")
//                false
//            }
//        }
//    }

    fun receiveMouseMove(xpos: Float, ypos: Float) {

        // TODO:
        //  将  xpos,ypos 限制在窗口坐标区域内?

        if (mouseLeftState) {
            mouseMoveCallback?.invoke(GLFW_MOUSE_BUTTON_LEFT, xpos, ypos)
        }

        if (mouseRightState) {
            mouseMoveCallback?.invoke(GLFW_MOUSE_BUTTON_RIGHT, xpos, ypos)
        }

        if (mouseMiddleState) {
            mouseMoveCallback?.invoke(GLFW_MOUSE_BUTTON_MIDDLE, xpos, ypos)
        }
    }

    fun getCursorPos(): Vector2f {
        var curPosX: Float
        var curPosY: Float
        MemoryStack.stackPush().use { stack ->
            val x = stack.mallocDouble(1)
            val y = stack.mallocDouble(1)
            glfwGetCursorPos(window.winHandle, x, y)
            curPosX = x[0].toFloat()
            curPosY = y[0].toFloat()
        }
        return Vector2f(curPosX, curPosY)
    }


    fun mouseBegin(block: (Int, Float, Float) -> Unit) {
        mouseBeginCallback = block
    }

    fun mouseMove(block: (Int, Float, Float) -> Unit) {
        mouseMoveCallback = block
    }

    fun mouseEnd(block: (Int, Float, Float) -> Unit) {
        mouseEndCallback = block
    }
}

class InputMgr(val window: Window) {

    //  键盘事件
    val keyboardMgr = KeyBoardMgr()

    // 鼠标事件
    val mouseMgr = MouseMgr(window)
}